//-----------------------------------------------------------------------------
//  Copyright (c) 2013 by HangZhou HenqgQiao Design Corporation. All rights reserved.
//
//  Project  : 
//  Module   : over sample the input data with 8-phases 311M clock
//  Parent   : 
//  Children : 
//
//  Description: 
//
//  Parameters:
//  Local Parameters:
//
//  Notes       : 
//
//  Multicycle and False Paths

module FRM_MPI(
   input                         FRM_RESET,

   input                         MPI_CLK,
   input[7:0]                    MPI_ADDR,
   input                         MPI_CS,
   input                         MPI_WE,
   input[15:0]                   MPI_WD,
   output reg[15:0]              MPI_RD,
   output reg                    MPI_IRQ,

   output[3:0]                   MPI_TJ0_ADDR,
   output                        MPI_TJ0_WE,
   output[7:0]                   MPI_TJ0_WD,
   input[7:0]                    MPI_TJ0_RD,

   output[3:0]                   MPI_RJ0_ADDR,
   input[7:0]                    MPI_RJ0_RD,

   output reg                    MPI_J0_MODE,

   input[3:0]                    MPI_RPC_B1_ERRCNT,
   input                         MPI_RPC_B1_STROBE,

   input                         MPI_OOF
   );

reg[2:0]                         RPC_B1_STROBE_SREG;
reg[3:0]                         RPC_B1_ERRCNT;
reg                              RPC_B1_EN;
reg[15:0]                        MPI_B1_ERRCNT;

reg                              RALM_OOF;
reg                              MPI_WTC_OOF;
reg                              MPI_RTS_OOF;

reg                              MPI_IRQM_OOF;



// ++++++++++++++++++             Section 0: Address Map Table          ++++++++++++++++++  //
// 0x0000            Module Version
// 0x000A            J1 mode
// 0x0040            OOF/LOF alarm
// 0x0080-0x008F     The tramsmited J1 sequence
// 0x00A0-0x00AF     The received J1 sequence



// Rx J1 Address map
  assign MPI_RJ0_ADDR[3:0]      = MPI_ADDR[3:0];
// Tx J1 Address map
  assign MPI_TJ0_ADDR[3:0]      = MPI_ADDR[3:0];
  assign MPI_TJ0_WE             = MPI_WE==1'b1 && MPI_ADDR[7:4]==4'h8 && MPI_CS==1'b1;
  assign MPI_TJ0_WD[7:0]        = MPI_WD[7:0];

always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 ) begin
      MPI_J0_MODE                            <= 1'b0;
      MPI_IRQM_OOF                           <= 1'b0;            
   end
   else if ( MPI_WE==1'b1 && MPI_CS==1'b1 ) begin
      case ( MPI_ADDR[7:0] )
      8'h08: MPI_IRQM_OOF                    <= MPI_WD[0];
      8'h0A: MPI_J0_MODE                     <= MPI_WD[0];
      default: ;
      endcase
   end
end

always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      MPI_RD[15:0]                           <= 16'd0;
   else begin
      if ( MPI_ADDR[7:4]==4'h8 ) begin
         MPI_RD[15:8]                        <= 8'd0;
         MPI_RD[7:0]                         <= MPI_TJ0_RD[7:0];
      end
      else if ( MPI_ADDR[7:4]==4'hA ) begin
         MPI_RD[15:8]                        <= 8'd0;
         MPI_RD[7:0]                         <= MPI_RJ0_RD[7:0];
      end
      else begin
         case ( MPI_ADDR[7:0] )
         8'h00: MPI_RD[15:0]                 <= 16'h1000;
         8'h08: MPI_RD[15:0]                 <= {15'd0, MPI_IRQM_OOF};
         8'h0A: MPI_RD[15:0]                 <= {15'd0, MPI_J0_MODE};
         8'h40: begin
                MPI_RD[15:8]                 <= {6'd0, MPI_RTS_OOF, MPI_RTS_OOF};
                MPI_RD[7:0]                  <= {6'd0, MPI_WTC_OOF, MPI_WTC_OOF};
         end
         8'h50: MPI_RD[15:0]                 <= MPI_B1_ERRCNT[15:0];
         default:MPI_RD[15:0]                <= 16'h0000;
         endcase
      end
   end
end




// ++++++++++++++++++        MPI performence counters  generate          ++++++++++++++++++  //
always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      RPC_B1_STROBE_SREG[2:0]                <= 3'd0;
   else
      RPC_B1_STROBE_SREG[2:0]                <= {RPC_B1_STROBE_SREG[1:0], MPI_RPC_B1_STROBE};
end
always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      RPC_B1_ERRCNT[3:0]                     <= 4'd0;
   else if ( RPC_B1_STROBE_SREG[2]==1'b0 && RPC_B1_STROBE_SREG[1]==1'b1 )
      RPC_B1_ERRCNT[3:0]                     <= MPI_RPC_B1_ERRCNT[3:0];
end
always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      RPC_B1_EN                              <= 1'b0;
   else
      RPC_B1_EN                              <= RPC_B1_STROBE_SREG[2]==1'b0 && RPC_B1_STROBE_SREG[1]==1'b1;
end

always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      MPI_B1_ERRCNT[15:0]                   <= 16'd0;
   else begin
      if ( MPI_WE==1'b1 && MPI_ADDR[7:0]==8'h50 && MPI_CS==1'b1 )
         MPI_B1_ERRCNT[15:0]                <= 16'd0;
      else if ( RPC_B1_EN==1'b1 )
         MPI_B1_ERRCNT[15:0]                <= MPI_B1_ERRCNT[15:0] +{12'd0, RPC_B1_ERRCNT[3:0] };
   end
end


// ++++++++++++++++++        MPI alarm registers          ++++++++++++++++++  //
always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      RALM_OOF                              <= 1'b0;
   else
      RALM_OOF                              <= MPI_OOF;
end
always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      MPI_RTS_OOF                           <= 1'b0;
   else
      MPI_RTS_OOF                           <= RALM_OOF;
end
always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      MPI_WTC_OOF                           <= 1'b0;
   else begin
      if ( MPI_WE==1'b1 && MPI_ADDR[7:0]==8'h40 && MPI_CS==1'b1 )
         MPI_WTC_OOF                        <= 1'b0;
      else
         MPI_WTC_OOF                        <= MPI_WTC_OOF | RALM_OOF;
   end
end


always @( posedge MPI_CLK or posedge FRM_RESET) begin
   if ( FRM_RESET==1'b1 )
      MPI_IRQ                               <= 1'b0;
   else
      MPI_IRQ                               <= (MPI_RTS_OOF & MPI_IRQM_OOF);
end


endmodule
